﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using PubSubWeb.Model;

namespace PubSubWeb.Container
{
    public class InMemorySubscriptionStore : ISubscriptionStore
    {
        private Dictionary<string, Topic> topicsTopicURL;

        private Dictionary<string, Dictionary<string, Topic>> topicsByCallbackURL;

        public InMemorySubscriptionStore()
        {
            this.topicsByCallbackURL = new Dictionary<string, Dictionary<string, Topic>>();
            this.topicsTopicURL = new Dictionary<string, Topic>();
        }

        #region ISubscriptionStore Members

        public Subscription AddSubscription(
                                    string callback, 
                                    string topic, 
                                    SubscriptionVerificationType verificationType, 
                                    int leaseSeconds, 
                                    string secret, 
                                    string verifyToken)
        {
            Subscription subscription;

            lock (this)
            {
                // If the topic does not exist, create it
                if (!this.topicsTopicURL.ContainsKey(topic))
                {
                    this.topicsTopicURL[topic] = new Topic(topic);
                }

                Topic topicObject = this.topicsTopicURL[topic];

                if (!this.topicsByCallbackURL.ContainsKey(callback))
                {
                    this.topicsByCallbackURL[callback] = new Dictionary<string, Topic>();
                }

                if (!this.topicsByCallbackURL[callback].ContainsKey(topic))
                {
                    this.topicsByCallbackURL[callback][topic] = topicObject;
                }

                if (!topicObject.Subscriptions.ContainsKey(callback))
                {
                    topicObject.Subscriptions[callback] = new Subscription(
                                                                    callback,
                                                                    topic,
                                                                    verificationType,
                                                                    leaseSeconds,
                                                                    secret,
                                                                    verifyToken);
                }

                subscription = topicObject.Subscriptions[callback];
            }

            return subscription;
        }

        public void RemoveSubscription(
                                    string callback, 
                                    string topic, 
                                    SubscriptionVerificationType verificationType, 
                                    string secret, 
                                    string verifyToken)
        {
            lock (this)
            {
                this.topicsTopicURL.Remove(topic);

                if (this.topicsByCallbackURL.ContainsKey(callback))
                {
                    if (this.topicsByCallbackURL[callback].ContainsKey(topic))
                    {
                        this.topicsByCallbackURL[callback][topic].Subscriptions.Remove(callback);

                        if (this.topicsByCallbackURL[callback][topic].Subscriptions.Count == 0)
                        {
                            this.topicsByCallbackURL[callback].Remove(topic);
                        }
                    }
                }
            }
        }

        public List<Subscription> GetSubscribersForTopic(string topicUrl)
        {
            if (this.topicsTopicURL[topicUrl] != null)
            {
                return this.topicsTopicURL[topicUrl].Subscriptions.Values.ToList<Subscription>();
            }

            return null;
        }

        public List<Topic> GetTopicsForSubscription(string callbackUrl)
        {
            if (this.topicsByCallbackURL[callbackUrl] != null)
            {
                return this.topicsByCallbackURL[callbackUrl].Values.ToList<Topic>();
            }

            return null;
        }

        #endregion
    }
}
